/*
增加真实时间转换
增加可配置参数
    ————平均每小时顾客数
    ————单个窗口平均每小时服务顾客数
    ————是否要显示模拟过程。
所有参数交互式输入
*/

#ifndef BANK_H_
#define BANK_H_

#include <iostream>
#include <queue>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Customer
{
  private:
    int arriveTime;
    int getServeTime;
    int WaitingTime;

  public:
    Customer(int arrTime) : arriveTime(arrTime){};
    Customer &set_getServeTime(int gseTime)
    {
        getServeTime = gseTime;
        return *this;
    };
    Customer &set_WaitingTime()
    {
        WaitingTime = getServeTime - arriveTime;
        return *this;
    };
    int get_WaitingTime() const { return WaitingTime; };
};

class RealTime
{
  private:
    int hour;
    int minter;
    int second;
    string showType;

  public:
    RealTime(int h, int m, int s, const string &type = "clock") : hour(h), minter(m), second(s), showType(type){};
    RealTime(int sumSeconds, const string &type = "time")
    {
        hour = sumSeconds / 3600;
        minter = (sumSeconds % 3600) / 60;
        second = (sumSeconds % 3600) % 60;
        showType = type;
    };
    const RealTime &setStartTime(const RealTime &start)
    {
        hour += start.hour;
        minter += start.minter;
        second += start.second;
        return *this;
    }
    friend ostream &operator<<(ostream &out, const RealTime &time)
    {
        if (time.showType == "clock")
        {
            out << time.hour << ":" << time.minter << ":" << time.second << endl;
            return out;
        }
        if (time.showType == "time")
        {
            if (time.hour == 0 && time.minter == 0)
            {
                out << time.minter << "秒" << endl;
            }
            else if (time.hour == 0)
            {
                out << (time.minter + (double)time.second / 60) << "分钟" << endl;
            }
            else
            {
                out << (time.hour + (double)time.minter / 60 + (double)time.second / 3600) << "小时" << endl;
            }
            return out;
        }
        out << "the time show time is wrong" << endl;
        return out;
    }
};

class Bank
{
  private:
    bool ifShowProcess = false; //是否要展示模拟过程
    double currTime = 0;        //计时器，当前的时间，单位s.
    //模拟参数
    double workTime = 8 * 60 * 60; //总模拟时间(秒)
    int windowNums = 1;            //银行窗口数。
    double ArriNums = 12;          //平均每小时顾客数量
    double ability = 8;            //单个窗口平均每小时服务客户数量。
    // 模拟结果统计
    double sumCusServed = -1;         //总服务顾客数(营业时间结束时，仍然可能有未服务的顾客)
    double lastCus = -1;              //营业结束时，仍在队列中，没有服务的客户。
    double sumCusArrive = -1;         //总到达顾客数。
    double sumWaitingTime = -1;       //所有已服务客户的等待时间
    double aver_waitingTime = -1;     //平均每位客户等待时间=sumWaitingTime/sumCusServed
    double per_second_servedCus = -1; //单位时间服务客户数=总服务顾客数/workTime
    double queSizeMax = -1;           //今日银行排队的最长是多少。
    double queSizeMin = -1;           //今日银行排队的最短是多少
    // 等候队列
    queue<Customer> waitingQueue;
    // 服务完成客户列表
    vector<Customer> servedQueue;

  public:
    Bank();
    bool ifCustomerArrive() const;
    bool ifWindowsIdly() const;
    void simulation(int rounds = 1);
    friend ostream &operator<<(ostream &out, Bank &bank);
};

#endif /* BANK_H_ */

// 结构能简单就简单，不要太多层次结构，除非真的必须。
// 不要为了代码阅读而刻意增加太多层次，尽量用注释搞定。
// 直接直接再直接，需求要核心简单，再不断完善，不要一次考虑太多维度，先实现，再有优化
